#pragma once
#include <string>
#include <jsoncpp/json/json.h>
#include "log.hpp"

using namespace std;

enum {
    right_ans = 0,
    div_by_zero,
    mod_by_zero,
    invalid_op
};

const string sep = " ";
const string package_ch = "\n";

// 封装报头
// ->"len\nx + y"
// ->"len\nresult status"
bool encapsulate(string *data) {
    int data_len = data->size();
    if(data_len <= 0) {
        lg(WARNING, "封装失败");
        return false;
    }
    string packet = to_string(data_len);
    packet += package_ch;
    packet += *data;
    packet += package_ch;
    *data = packet;
    return true;
}

// 解包
bool decapsulate(string *date, string &packet) {
    size_t pos_of_package_ch = packet.find(package_ch);
    if(pos_of_package_ch == string::npos) {
        lg(WARNING, "解包失败");
        return false;
    }
    string len_str = packet.substr(0, pos_of_package_ch);
    int date_len = stoi(len_str);
    size_t total_len = len_str.size() + date_len + 2;
    if(total_len > packet.size()) {
        lg(WARNING, "date_len err");
        return false;
    }
    *date = packet.substr(pos_of_package_ch + 1, date_len);
    // 去掉分离出来的部分
    packet.erase(0, total_len);
    return true;
}


class request {
public:
    request() {}
    request(int x, int y, char op) : _x(x), _y(y), _op(op){

    }

    //->"x op y"
    void serializer(string *s) const {
    #ifdef MY_VERSION
        *s = to_string(_x);
        *s += sep;
        *s += _op;
        *s += sep;
        *s += to_string(_y);
        lg(INFO, "request序列化成功");
    #else 
    Json::Value v;
    v["x"] = _x;
    v["op"] = _op;
    v["y"] = _y;
    Json::StyledWriter w;
    *s = w.write(v);
    #endif
    }

    //-> 'x' 'op' 'y'
    void deserializer(const string& s) {
    #ifdef MY_VERSION
        size_t left_x = s.find(sep);
        if(left_x == string::npos) {
            lg(WARNING, "request反序列化失败");
            return;
        }
        size_t right_y = s.rfind(sep);
        if(right_y == left_x) {
            lg(WARNING, "request反序列化失败");
            return;
        }
        _x = stoi(s.substr(0, left_x));
        _op = s[left_x + 1];
        _y = stoi(s.substr(right_y + 1));
        lg(INFO, "request反序列化成功");
    #else 
        Json::Value in;
        Json::Reader r;
        r.parse(s, in);
        _x = in["x"].asInt();
        _op = in["op"].asInt();
        _y = in["y"].asInt();
    #endif
    }

    void print() const {
        cout <<"get a request: " << _x << _op << _y << endl;
    }

    int _x;
    int _y;
    char _op;
};

class response {
public:
    response() {}
    response(int res, int status = right_ans) :_result(res), _status(status) {

    }
    //->"result status"
    void serializer(string *s) const {
    #ifdef MY_VERSION
        *s = to_string(_result);
        *s += sep;
        *s += to_string(_status);
        lg(INFO, "response序列化成功");
    #else 
        Json::Value root;
        root["result"] = _result;
        root["status"] = _status;
        Json::StyledWriter w;
        *s = w.write(root);
    #endif
    }
    
    //->"result" "status"
    void deserializer(const string &s) {
    #ifdef MY_VERSION
        size_t pos_of_sep = s.find(sep);
        if(pos_of_sep == string::npos) {
            lg(WARNING, "response反序列化失败");
            return;
        }
        _result = stoi(s.substr(0, pos_of_sep));
        _status = stoi(s.substr(pos_of_sep + 1));
        lg(INFO, "response反序列化成功");
    #else
        Json::Value in;
        Json::Reader r;
        r.parse(s, in);
        _result = in["result"].asInt();
        _status = in["status"].asInt();
    #endif
    }
    
    string get_result() {
        switch (_status) {
            case right_ans:
                return "right_ans";
            case div_by_zero: 
                return "div_by_zero";
            case mod_by_zero: 
                return "mod_by_zero";
            case invalid_op: 
                return "invalid_op";
            default:
                return "unknown err";
        }
    }

    int _result;
    int _status;
};